package admin_service

import (
	"fmt"
	"shop/common/log"
	"shop/config"
	"shop/config/constant"
	"shop/dao"
	"shop/entity"
	"shop/service"
	"shop/utils/convertutil"
	"shop/utils/genutil"
	"shop/utils/result"
	"shop/utils/wxpay"
)

func GetOrderList(shopId, pageNo, pageSize int, orderNo string, fromTime int64, toTime int64, orderStatus int) *result.Result {
	db := dao.GetDB().Table(entity.TableNameOrderInfo).Where("shop_id", shopId)
	if orderStatus == constant.OrderStatusRefunding || orderStatus == constant.OrderStatusRefunded {
		db.Where("refund_count > 0")
	} else if orderStatus != 0 {
		db.Where("order_status", orderStatus)
	}
	if orderNo != "" {
		db.Where("order_no", orderNo)
	}
	db.Where("create_time >= ?", fromTime)
	if toTime > 0 {
		db.Where("create_time <= ?", toTime)
	}

	count := new(int64)
	db.Count(count)
	list := make([]*entity.OrderInfo, 0)
	db.Offset((pageNo - 1) * pageSize).Order("create_time DESC").Limit(pageSize).Find(&list)
	for _, order := range list {
		order.ParseGoodsList()
	}
	return result.Ok(entity.Page{
		Total: *count,
		List:  list,
	})
}

const (
	CancelAndDelete = 1 // 取消并删除订单
	SendGoods       = 2 // 发货
	Refund          = 3 // 退款
)

type UpdateOrderStatusParams struct {
	OrderNo        string `json:"orderNo,omitempty"`
	Command        int    `json:"command,omitempty"`
	RefundReason   string `json:"refundReason,omitempty"` // 退款时需要
	RefundGoodsMap []bool `json:"refundGoodsMap,omitempty" `
}

func UpdateOrderStatus(shopId int, params *UpdateOrderStatusParams) (res *result.Result) {
	log.Debugf("更新订单状态：%v", convertutil.ToJsonString(params))

	tx := dao.GetTx()
	defer func() {
		res = dao.CommitByResult(res, tx)
	}()
	order := new(entity.OrderInfo)
	tx.Table(entity.TableNameOrderInfo).Where("order_no=? and shop_id=?", params.OrderNo, shopId).Take(order)
	if order.OrderNo == "" {
		return result.Fail("订单不存在")
	}

	if params.Command == CancelAndDelete {
		if order.OrderStatus != constant.OrderStatusNotPay {
			return result.Fail("未付款的订单才能取消")
		}
		rows := tx.Table(entity.TableNameOrderInfo).Where("order_no", order.OrderNo).Delete(nil).RowsAffected
		return result.Ok(rows)
	} else if params.Command == Refund {
		if order.OrderStatus == constant.OrderStatusNotPay || order.OrderStatus == constant.OrderStatusFinished {
			return result.Fail("未付款和已完成的订单不支持退款")
		}
		order.ParseGoodsList()
		if params.RefundGoodsMap == nil || len(params.RefundGoodsMap) != len(order.GoodsList) {
			return result.Fail("退款商品参数格式错误")
		}
		order.RefundCount = 0
		refundPrice := int64(0)
		refundNo := order.OrderNo + "-" + genutil.RandStr(10) // 本次退款的退款号
		for i, orderGoods := range order.GoodsList {
			if params.RefundGoodsMap[i] && orderGoods.RefundNo == "" {
				orderGoods.RefundNo = refundNo
				orderGoods.RefundReason = params.RefundReason
				refundPrice += int64(orderGoods.Price * orderGoods.Count)
			}
			if orderGoods.RefundNo != "" {
				order.RefundCount++
				for _, orderGoods := range order.GoodsList {
					goodsInDB := service.GetGoodsById(orderGoods.GoodsId)
					// 将库存加回去
					if err := entity.UpdateGoodsStockAdd(goodsInDB, orderGoods.PropertyMap, orderGoods.Count); err != nil {
						return result.Fail(err.Error())
					}
					if err := tx.Exec("update goods set count=?, property_list=? where id=?", goodsInDB.Count, goodsInDB.PropertyListStr, goodsInDB.Id).Error; err != nil {
						log.Errorf("数据库更新失败，库存更新，更新property_list失败，err: %v", err)
						return result.Fail("库存更新失败")
					}
				}
			}
		}
		if refundPrice == 0 {
			return result.Fail("退款价格为0")
		}

		shop := service.GetShopInfo(shopId)
		merchant := config.GetMerchantConfByShopId(shopId)
		if merchant == nil || merchant.ShopId == 0 {
			return result.Fail("商家不存在或已下线")
		}
		if order.RefundCount == len(order.GoodsList) { // 全部商品都要退款，订单状态就改为已退款
			order.OrderStatus = constant.OrderStatusRefunded
			if order.TakeType == constant.TakeTypeTakeOut { // 配送费和打包费都退了
				refundPrice += int64(shop.SendingPrice)
				refundPrice += int64(shop.PackingPrice)
			}
		}
		cli := wxpay.NewClient(merchant.WxMpAppId, merchant.WxPayMchId, merchant.WxPayApiKey)
		cli.SetCertData(merchant.CertPEMPublicKey, merchant.CertPEMPrivateKey)
		_, err := cli.Refund(&wxpay.RefundParams{
			TransactionId: order.WxPayTransactionId,
			OutRefundNo:   refundNo,
			TotalFee:      order.PayPrice,
			RefundFee:     refundPrice,
		})
		if err != nil {
			return result.Fail("退款失败，" + err.Error())
		}

		order.GoodsListToStr()
		rows := tx.Table(entity.TableNameOrderInfo).Where("order_no", order.OrderNo).Updates(order).RowsAffected
		return result.Ok(rows)
	}
	return result.Fail(fmt.Sprintf("不支持的命令：%d", params.Command))
}
